package ba07_allTest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @author HLF
 * @version V1.0
 * @package ba07_allTest
 * @date 2021/10/18 19:48
 */
@Component
@Aspect
public class Aspect07 {

    @Pointcut(value = "execution(* ba07_allTest.OtherServiceImpl.doThird(..))")
    private void doThird() {
    }

    @Before(value = "doThird()")
    public void myBefore(JoinPoint joinPoint) {
        String name = joinPoint.getSignature().getName();//可以这样获取目标方法名
        System.out.println("1.前置通知Before：执行目标方法之前执行");
    }

    @AfterReturning(value = "doThird()", returning = "res")
    public void myAfterReturning(JoinPoint joinPoint, Object res) {
        System.out.println("2.后置通知AfterReturning：执行目标方法之后执行");
    }

    @Around(value = "doThird()")
    public Object myAround(ProceedingJoinPoint proceedingJoinPoint) {
        System.out.println("3.环绕通知Around：执行目标方法之前执行");
        Object res = null;

        try {
            //执行目标方法
            res = proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

        System.out.println("3.环绕通知Around：执行目标方法之后执行");

        //环绕通知可以修改目标方法的返回值，无论目标方法的返回值类型是基本数据类型还是引用数据类型都可以修改
        return "在环绕通知的切面方法中修改了目标方法的返回值";
        //return res;
    }

    @AfterThrowing(value = "doThird()", throwing = "e")//相当于catch块
    public void myAfterThrowing(JoinPoint joinPoint, Exception e) {
        System.out.println("4.异常通知AfterThrowing：发生异常时执行" + e.getMessage());
        //可以在这里给管理员短信，邮件提示，通知管理员代码执行发生了异常
    }

    @After(value = "doThird()")
    public void myAfter(JoinPoint joinPoint) {
        System.out.println("5.最终通知After：无论什么时候都会通知，即使发生了异常");
    }
}

/**
 * Spring5.2.8之后版本：
 * 多个切面时：
 * 正常执行顺序：Around前置  Before  目标方法  AfterReturning  After  Around后置
 * 出异常时顺序：Around前置  Before  目标方法  AfterThrowing  After  Around后置
 * <p>
 * 单个切面时：
 * 正常执行顺序：@Before=====目标方法=====@AfterReturning=====@After
 * 出异常时顺序：@Before=====目标方法=====@AfterThrowing=====@After
 */
